package com.atomscat.lottery.service;

import com.atomscat.lottery.entity.vo.response.LotteryRecordResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.ReactiveListOperations;
import org.springframework.data.redis.core.ReactiveRedisTemplate;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;

import java.util.List;
import java.util.Random;
import java.util.concurrent.atomic.AtomicReference;

@Slf4j
@Service
@RequiredArgsConstructor
public class LotteryService {
    private final LotteryRecordService lotteryRecordService;
    private final ReactiveRedisTemplate<String, String> reactiveRedisTemplate;

    private static final String PARTICIPANT_LIST = "lottery:participants:";
    private static final String PRIZE_LIST = "lottery:prizes:";

    // 获取ReactiveListOperations
    private ReactiveListOperations<String, String> participantOps() {
        return reactiveRedisTemplate.opsForList();
    }

    // 添加参与者
    public void addParticipant(Long activityId, String participantId) {
        participantOps().leftPush(PARTICIPANT_LIST + activityId, participantId).subscribe(count -> {
            if (count > 0) {
                log.info("参与者 {} 已添加到活动 {} 的抽奖列表中", participantId, activityId);
            } else {
                log.warn("参与者 {} 添加失败，活动 {} ", participantId, activityId);
                throw new RuntimeException("添加参与者失败");
            }
        });
    }

    // 添加奖品
    public void addPrize(Long activityId, Long prizeId, String prize) {
        participantOps().leftPush(PRIZE_LIST + activityId + ":" + prizeId, prize).subscribe(count -> {
            if (count > 0) {
                log.info("奖品 {} 已添加到活动 {} 的抽奖列表中", prize, activityId);
            } else {
                log.warn("奖品 {} 添加失败，活动 {} ", prize, activityId);
                throw new RuntimeException("添加奖品失败");
            }
        });
    }

    public Mono<Boolean> deletePrize(Long activityId, String prizeId) {
       return participantOps().delete(PRIZE_LIST + activityId + ":" + prizeId);
    }

    public void deleteParticipant(Long activityId) {
        participantOps().delete(PARTICIPANT_LIST + activityId).subscribe(count -> {
           log.info("delete {} ", activityId);
        });
    }

    // 执行抽奖
    public LotteryRecordResponse drawLottery(Long activityId, Long prizeId) {
        // 获取参与者和奖品列表
        Mono<List<String>> participantsMono = participantOps().range(PARTICIPANT_LIST + activityId, 0, -1).collectList();
        Mono<List<String>> prizesMono = participantOps().range(PRIZE_LIST + activityId + ":" + prizeId, 0, -1).collectList();
        AtomicReference<Long> winnerId = new AtomicReference<>();

        Mono.zip(participantsMono, prizesMono)
                .flatMap(tuple -> {
                    List<String> participants = tuple.getT1();
                    List<String> prizes = tuple.getT2();

                    if (participants.isEmpty() || prizes.isEmpty()) {
                        return Mono.just("没有足够的参与者或奖品!");
                    }
                    // 随机选择一个参与者和奖品
                    Random random = new Random();
                    String winner = participants.get(random.nextInt(participants.size()));
                    String prize = prizes.get(random.nextInt(prizes.size()));
                    // 从列表中移除已抽中的奖品和参与者
                    participantOps().remove(PARTICIPANT_LIST + activityId, 1, winner).subscribe(count -> {
                        if (count > 0) {
                            log.info("参与者 {} 已从活动 {} 的抽奖列表中移除", winner, activityId);
                        } else {
                            log.warn("参与者 {} 移除失败，活动 {} ", winner, activityId);
                            throw new RuntimeException("移除参与者失败");
                        }
                    });
                    participantOps().remove(PRIZE_LIST + activityId + ":" + prizeId, 1, prize).subscribe(count -> {
                        if (count > 0) {
                            log.info("奖品 {} 已从活动 {} 的抽奖列表中移除", prize, activityId);
                        } else {
                            log.warn("奖品 {} 移除失败，活动 {} ", prize, activityId);
                            throw new RuntimeException("移除奖品失败");
                        }
                    });
                    // 保存抽奖记录
                    log.info("活动:{}, 中奖者: {}, 奖品: {}", activityId, winner, prize);
                    lotteryRecordService.createLotteryRecord(activityId, Long.valueOf(winner), prizeId);
                    return Mono.just(winner);
                }).doOnNext(winner -> {
                    winnerId.set(Long.valueOf(winner));
                    log.info("活动:{}, 中奖者: {}, 奖品: {}", activityId, winner, prizeId);
                }).subscribe(winner -> {
                    winnerId.set(Long.valueOf(winner));
                    log.info("活动:{}, 中奖者: {}, 奖品: {}", activityId, winner, prizeId);
                });
        return new LotteryRecordResponse(activityId, winnerId.get(), prizeId);
    }
}
